package com.googlecode.gunncs.mechanism;

import java.util.ArrayList;
import java.util.Vector;

import maze.Controller;
import maze.Direction;
import maze.Node;
import maze.Path;
import maze.PathSegment;

import com.googlecode.gunncs.mechanism.component.NodeFoundEvent;
import com.googlecode.gunncs.mechanism.component.NodeFoundListener;

/**
 * The API that <strong>Mechanisms</strong> needs to expose to
 * <strong>Controls</strong>.
 * 
 * <p>
 * These are all the methods I need exposed to implement a search algorithm.
 * </p>
 * <p>
 * Consider this the bot's API. <strong>NB</strong>: details here are still
 * being worked out, at meetings, on Google Docs, etc. None of this should be
 * considered finalized.
 * </p>
 * <strong>Basic structure</strong>:
 * <p>
 * Controller calls {@link #go()}. Robot goes until it hits a place where a
 * {@link Node} should go. It then returns from {@link #go()} and fires an event
 * to controller ({@link NodeFoundEvent}).
 * </p>
 * <p>
 * Controller may then query data (not before, nor after). It will then
 * instruct a path to move. It will then call {@link #go()} again and wait
 * for another event.
 * </p>
 * 
 * Development stage: might need refinement, but should be usable as-is.
 * 
 * @see NodeFoundEvent
 * @see PathSegment
 * @see Node
 * @see Controller
 * @see Direction
 * @author Calvin
 */
public interface AbstractBot {
	// TODO: Provide a human-interfacing reference implementation (this is my (Calvin's) APCS final project).
	/**
	 * Go to the next necessary stop point. This method should be asynchronous
	 * (return immediately).
	 * 
	 * Essentially means corridor-follow, but with some nasty exceptions (most
	 * of which involve open spaces). See recent discussion on
	 * "rooms and doors".
	 * <p>
	 * <strong>Precondition </strong>: Bot is stopped (i.e., not currently
	 * executing this).<br />
	 * <strong>Postcondition</strong>: Bot is stopped at a "door" (i.e.,
	 * "intersection" in the old parlance). It will fire an event to the
	 * controller.
	 * </p>
	 */
	public void go();

	/**
	 * I'm actually not sure why I'd need this.
	 * 
	 * But I might, and it should be keeping track.
	 * <p>
	 * <strong>Precondition </strong>: The bot is stopped.<br />
	 * <strong>Postcondition</strong>: The bot is unaffected.
	 * </p>
	 * 
	 * @return The cardinal direction the robot currently faces.
	 */
	public Direction currentDirection();

	/**
	 * Turn <em>in place</em> (roughly, at least) to face given Direction.
	 * <p>
	 * <strong>Precondition </strong>: Bot is stopped. It should be an error to
	 * call this when the robot is moving (i.e. in {@link #go()}).<br />
	 * <strong>Postcondition</strong>: Bot is facing <strong>face</strong>. It
	 * has not moved.
	 * </p>
	 * 
	 * @param face {@link Direction} to face.
	 */
	public void turnTo(Direction face);

	/**
	 * Follow a given path.
	 * 
	 * Note that the distances should only be used for verification purposes; 
	 * only the turn data is *really* important.
	 */
	public void follow(Path path);

	/**
	 * Open directions.
	 * 
	 * @return A Vector of Direction objects representing
	 *         the directions in which the bot can currently travel. Remember
	 *         that these directions are absolute, not relative.
	 */
	public Vector openDirections();

	/**
	 * Subscribes a provided NodeFoundListener to be notified when a node is
	 * found
	 * 
	 * @param l
	 */
	public void addNodeFoundListener(NodeFoundListener l);

	/**
	 * Unsubscribes a provided NodeFoundListener to be notfied when a node is
	 * found
	 * 
	 * @param l
	 */
	public void removeNodeFoundListener(NodeFoundListener l);
}